package it.uni.bo.monitoring.sla.context;

import it.uni.bo.monitoring.sla.chain.availability.Reliability;
import it.uni.bo.monitoring.sla.chain.availability.ReliabilityManager;
import it.uni.bo.monitoring.sla.chain.causality.PatternManager;
import it.uni.bo.monitoring.sla.chain.latency.Latency;
import it.uni.bo.monitoring.sla.chain.latency.LatencyManager;
import it.uni.bo.monitoring.sla.chain.throughput.Throughput;
import it.uni.bo.monitoring.sla.chain.throughput.ThroughputManager;
import it.uni.bo.monitoring.sla.parser.SlaBean;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.SessionFactory;


public class MonitoringContext {

	private List<ComponentManager> automatonThroughputList;
	private List<ComponentManager> latencyList;
	private List<ComponentManager> automatonReliabilityList;
	private List<ComponentManager> automatonPatternList;

	public MonitoringContext(SlaBean sb, SessionFactory factory) {
		this.automatonThroughputList = createAutomatonThroughputList(sb.getThroughputList(), factory);
		this.latencyList = createLatencyList(sb.getLatencyList(), factory);
		this.automatonReliabilityList=createAutomatonReliabilityList(sb.getReliabilityList(), factory);
		this.automatonPatternList=createAutomatonPatternList(factory);
	}

	public List<ComponentManager> getAutomatonThroughputList() {
		return automatonThroughputList;
	}
	
	public List<ComponentManager> getLatencyList() {
		return latencyList;
	}
	
	public List<ComponentManager> getAutomatonReliabilityList() {
		return automatonReliabilityList;
	}
	
	public List<ComponentManager> getAutomatonPatternList() {
		return automatonPatternList;
	}
	
	private List<ComponentManager> createAutomatonThroughputList(List<Throughput> tl, SessionFactory factory){
		List<ComponentManager> raitList = new ArrayList<ComponentManager>();
		for(int i=0;i<tl.size();i++){
			int window = tl.get(i).getWindow().intValue();
			int numStates = (int) tl.get(i).getConcurrency();
			numStates = numStates + 2;
			AutomataState I= new AutomataState("Init");
			AutomataState l= new AutomataState("l1");
			AutomataState F= new AutomataState("l"+(numStates-1));
			I.addTransition(new AutomataTransition(l));
			for (int j=1; j<numStates-2; j++) {
				AutomataState tmp = l;
				l= new AutomataState("l"+(j+1));
				tmp.addTransition(new AutomataTransition(l));
				if(j==numStates-3)
					l.addTransition(new AutomataTransition(F, window));
			}			
			raitList.add(new ThroughputManager(numStates, I, F, factory));
		}
		return raitList;
	}
	
	private List<ComponentManager> createLatencyList(List<Latency> latencyList, SessionFactory factory) {
		List<ComponentManager> lmList = new ArrayList<ComponentManager>();
		for(int i=0;i<latencyList.size();i++)
			lmList.add(new LatencyManager(latencyList.get(i), factory));
		return lmList;
	}

	private List<ComponentManager> createAutomatonReliabilityList(List<Reliability> rl, SessionFactory factory){
		List<ComponentManager> raitList = new ArrayList<ComponentManager>();
		for(int i=0;i<rl.size();i++){
			int window = rl.get(i).getWindow().intValue();
			int numStates = (int) rl.get(i).getMaxFailures();
			numStates = numStates + 2;
			AutomataState I= new AutomataState("Init");
			AutomataState l= new AutomataState("l1");
			AutomataState F= new AutomataState("l"+(numStates -1));
			I.addTransition(new AutomataTransition(l));
			for (int j=1; j<numStates-2; j++) {
				AutomataState tmp = l;
				l= new AutomataState("l"+(j+1));
				tmp.addTransition(new AutomataTransition(l));
				if(j==numStates-3)
					l.addTransition(new AutomataTransition(F, window));
			}
			raitList.add(new ReliabilityManager(numStates, I, F, factory));
			/*
				ReliabilityManager rait = new ReliabilityManager(numStates, new AutomataState("l0"), new AutomataState("l"+(numStates-1)), factory);
				AutomataTransition mytransition = new AutomataTransition();
				mytransition.setSource(new AutomataState("l0"));
				mytransition.setTarget(new AutomataState("l1"));
				mytransition.setReset("x");
				rait.addTransition(mytransition);
				// add the transitions in the middle
				for (int j=1; j<numStates-2; j++) {
					AutomataTransition myt = new AutomataTransition();
					myt.setSource(new AutomataState("l"+j));
					myt.setTarget(new AutomataState("l"+(j+1)));
					rait.addTransition(myt);
				}
				// add the transition to the accepting state:
				AutomataTransition myt2 = new AutomataTransition();
				myt2.setSource(new AutomataState("l"+(numStates-2)));
				myt2.setTarget(new AutomataState("l"+(numStates-1)));
				Double tmpd = new Double(window);
				int tmpdi = tmpd.intValue();
				myt2.setGuard(tmpdi);
				rait.addTransition(myt2);
				raitList.add(rait);*/
		}
		return raitList;
	}
	
	private List<ComponentManager> createAutomatonPatternList(SessionFactory factory) {
		try {
			List<ComponentManager> automatonList = new ArrayList<ComponentManager>();
			int numStates = 6;
			numStates = numStates + 1;
			AutomataState E= new AutomataState("Error");
			AutomataTransition te = new AutomataTransition(E);
			AutomataState I= new AutomataState("Init", te);
			AutomataState l1= new AutomataState("l1", te);
			AutomataState l2= new AutomataState("l2", te);
			AutomataState l3= new AutomataState("l3", te);
			AutomataState l4= new AutomataState("l4", te);
			AutomataState l5= new AutomataState("l5", te);
			AutomataState l6= new AutomataState("l6", te);

			I.addTransition(new AutomataTransition(l1, "checkFlights"));
			
			l1.addTransition(new AutomataTransition(l1, "checkFlights"));
			l1.addTransition(new AutomataTransition(l2, "getFlightDetails"));
			
			l2.addTransition(new AutomataTransition(l1, "checkFlights"));
			l2.addTransition(new AutomataTransition(l2, "getFlightDetails"));
			l2.addTransition(new AutomataTransition(l3, "reserveFlight"));
			
			l3.addTransition(new AutomataTransition(l1, "checkFlights"));
			l3.addTransition(new AutomataTransition(l4, "cancelReservation"));
			l3.addTransition(new AutomataTransition(l5, "confirmFlightReservation"));
			
			l4.addTransition(new AutomataTransition(l1, "checkFlights"));
			
			l5.addTransition(new AutomataTransition(l1, "checkFlights"));
			l5.addTransition(new AutomataTransition(l6, "ticketDetails"));
			
			l6.addTransition(new AutomataTransition(l1, "checkFlights"));
			l6.addTransition(new AutomataTransition(l6, "getTicketDetails"));
			E.addTransition(new AutomataTransition(l1, "checkFlights"));

			PatternManager rm = new PatternManager(I, factory);
			automatonList.add(rm);
			return automatonList;
		} catch (Exception e) {
			return null;
		}
	}
}
